/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_loader_hal.h"
#include "sle_host_hal.h"
#include "sle_adapter_hdi.h"
#include "sle_hilog.h"

#ifndef __LITEOS_M__
#include <dlfcn.h>
#endif //__LITEOS_M__

static SleHdiOpts* g_sleHalOpts = NULL;

SleHalErrorCode GetSleHostHalOpts(SleHostHdiOpts *sleHostOpts)
{
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts->hostOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(sleHostOpts != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(sleHostOpts, g_sleHalOpts->hostOpts, sizeof(SleHostHdiOpts));
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode GetSleSeekHalOpts(SleSeekHdiOpts *sleSeekOpts)
{
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts->seekOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(sleSeekOpts != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(sleSeekOpts, g_sleHalOpts->seekOpts, sizeof(SleSeekHdiOpts));
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode GetSleAnnounceHalOpts(SleAnnounceHdiOpts *sleAnnounceOpts)
{
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts->announceOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(sleAnnounceOpts != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(sleAnnounceOpts, g_sleHalOpts->announceOpts, sizeof(SleAnnounceHdiOpts));
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode GetSleConnectHalOpts(SleConnectHdiOpts *sleConnectOpts)
{
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts->connectOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(sleConnectOpts != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(sleConnectOpts, g_sleHalOpts->connectOpts, sizeof(SleConnectHdiOpts));
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode GetSleSsapcHalOpts(SleSsapcHdiOpts *sleSsapcOpts)
{
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts->ssapcOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(sleSsapcOpts != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(sleSsapcOpts, g_sleHalOpts->ssapcOpts, sizeof(SleSsapcHdiOpts));
    return SLE_HAL_SUCCESS;
}

SleHalErrorCode GetSleSsapsHalOpts(SleSsapsHdiOpts *sleSsapsOpts)
{
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts->ssapsOpts != NULL, SLE_HAL_ERR_NOT_READY);
    SLE_ASSERT_AND_RETURN_RET(sleSsapsOpts != NULL, SLE_HAL_ERR_INVALID_PARAM);
    memcpy(sleSsapsOpts, g_sleHalOpts->ssapsOpts, sizeof(SleSsapsHdiOpts));
    return SLE_HAL_SUCCESS;
}

#ifndef __LITEOS_M__
static void *g_dlHandle = NULL;
typedef SleHdiErrorCode (*SleHdiInitOpts_t)(SleHdiOpts*);
SleHdiInitOpts_t g_sleHdiInitOpts = NULL;

//TODO: 后续将SLE_SO_LIB_DIR配置为sys cap
#ifndef SLE_SO_LIB_DIR
#ifdef SLE_CFG_ARM_AARCH64
#define SLE_SO_LIB_DIR "/vendor/lib64/libsle_vendor.z.so"
#else
#define SLE_SO_LIB_DIR "/vendor/lib/libsle_vendor.z.so"
#endif
#endif


static SleHalErrorCode LoaderStandardOpts(void)
{
    g_sleHdiInitOpts = (SleHdiInitOpts_t)SleHdiInitOpts;
    if (g_sleHdiInitOpts == NULL) {
        SLE_LOGE("g_sleHdiInitOpts SleHdiInitOpts null");
        return SLE_HAL_ERR_DRIVER_OR_SYSTEM;
    }
    return SLE_HAL_SUCCESS;
}
#endif // not __LITEOS_M__

SleHalErrorCode InitSleHal(void)
{
    SLE_LOGI("InitSleeHal in");
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts == NULL, SLE_HAL_SUCCESS);
    g_sleHalOpts = (SleHdiOpts*)malloc(sizeof(SleHdiOpts));
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_ERR_DRIVER_OR_SYSTEM);

    SleHalErrorCode ret = SLE_HAL_ERR_UNKNOWN;
#ifndef __LITEOS_M__
    ret = LoaderStandardOpts();
    SLE_ASSERT_AND_RETURN_RET(ret == SLE_HAL_SUCCESS, ret);
    SleHdiErrorCode result = g_sleHdiInitOpts(g_sleHalOpts);
    ret = SleHalGetErrorCode(result);
#else
    SleHdiErrorCode result = SleHdiInitOpts(g_sleHalOpts);
    ret = SleHalGetErrorCode(result);
#endif  //not __LITEOS_M__
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, ret, "SleHdiInitOpts fail(0x%{public}08X)", result);
    return ret;
}

SleHalErrorCode DeinitSleHal(void)
{
    SLE_LOGI("DeinitSleHal in");
    SLE_ASSERT_AND_RETURN_RET(g_sleHalOpts != NULL, SLE_HAL_SUCCESS);
    free(g_sleHalOpts);
    g_sleHalOpts->hostOpts = NULL;
    g_sleHalOpts->seekOpts = NULL;
    g_sleHalOpts->connectOpts = NULL;
    g_sleHalOpts->ssapcOpts = NULL;
    g_sleHalOpts->ssapsOpts = NULL;
    g_sleHalOpts = NULL;
#ifndef __LITEOS_M__
    g_sleHdiInitOpts = NULL;
    dlclose(g_dlHandle);
    g_dlHandle = NULL;
#endif // not  __LITEOS_M__
    return SLE_HAL_SUCCESS;
}
